<?php
/** 
 * @package AMFramework
 * @subpackage Core_MVC
 * @author Marcu Alexandru
 * @version 1.0 $Build 305b  
 */
defined('_INDEX') or die('Restricted');

class Amfw_Controller extends Amfw_Object {
	private $_task;
	private $_model; //Model object

	public static function display($layout = null) {
		if(is_null($layout)) {
			$layout = Amfw_Request::getv('task');
		}
		Amfw_Request::setv('layout', $layout);
	}
	
	// Public =================================================================
	public function init( $run = false )
	{
		// Daca init porneste cu parametrul $run true
		// va apela runTask fara parametri;
		$this->__initAll();

		$run ? $this->runTask() : null;
	}

	// Protected ==============================================================
	protected function _initTask() 
	{
		if(is_subclass_of($this,'Amfw_Controller')) 
		{
			$task = Amfw_Request::getv('task', null);

			if(isset( $task )) 
			{
				$this->_task = $task;
				return;
			}
			elseif(empty( $this->_task ))
			{
				$tmp = $this->mirror( $this );
				$this->_task = $tmp['controller_name'];
				Amfw_Request::setv('task',$this->_task);	//TODO: added March 31, watch this closely 
				return;
			}
		}
	}

	protected function runTask( $task = null ) 
	{
		// Metoda trebuie rulata intr-un controller;
		// daca este specificat un parametru $task,
		// atunci acel task va fi rulat indiferent de
		// ce s-a initializat.
		$task = isset( $task ) ? $task : $this->_task;

		//TODO: possible cache-related lines to put here		
		
		if(method_exists($this, $task))
		{
			$this->$task();
			return true;
		}
		else
		{
			// If we don't have a controller method then we
			// consider it to be a static page and we'll load 
			// the layout that has the name of the task 
			Amfw_Request::setv('layout',strtolower($task));//TODO: added strtolower here
			
			
			// TODO: issue a notice
			
			return false;
		}
	}

	protected function mirror( $object ) 
	{
		// Supraincarca metoda din clasa parinte 
		// adaugand functionalitate pentru controller
		$info = parent::mirror( $object );
		
		if($info !== false && stripos($info['name'], 'Controller') !== false):
			$pos = stripos($info['name'], 'Controller') + strlen('Controller') + 1;
			$controller_name = substr($info['name'], $pos);
			
			$info['controller_name'] = $controller_name; 
		endif;
		
		return $info;
	}
	/**
	 * Se accepta maxim un model pentru fiecare controller, metoda ia modelul,daca exista
	 * retinut ca proprietate in controller. Modelul se instantiaza doar cand este chemat,
	 * altfel poate si sa nu existe.
	 * @return Object
	 */
	protected function &getModel( ) {
		if(is_subclass_of($this,'Amfw_Controller')){
			if(!isset($this->_model)) 
			{
				$class_name = get_class($this);
				// Cuvantul `Controller` exista in numele clasei si este unic
				if(	strpos($class_name,'Controller') !== false && 
					strpos($class_name,'Controller') === strrpos($class_name,'Controller'))
				{
					$model = str_replace('Controller','Model',$class_name); //TODO: Toleranta daca modelul nu exista
					$this->_model = new $model(); 
				}
				else	// Clasa nu respecta conventia de nume; indiferent ca este sublcasa, o aruncam 
				{ 
					trigger_error(	"<u>Controller $class_name</u> does not meet the Amfw 
									naming conventions, and cannot retreive model.", E_USER_WARNING);
					return null; 
				}
			}
			return $this->_model;
		}
		else
		{
			return null;
		}
	}
	/**
	 * Metoda redirect trimite un header spre un alt task atunci cand nu urmeaza nimic
	 * in partea de prezentare a aplicatiei (nu este necesar un layout specific)
	 * @param String $path  Dupa root, calea spre care se trimite headerul
	 */
	protected function redirect($path) {
		$header = 'Location: '.Amfw_URI::root().$path;
		header($header);
	}
}